/***************************************************************************
 *   Copyright (C) 2006 by Archimedes Projekt   *
 *   thelsb@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "hpsceventhandler.h"
#include <QtNetwork/QTcpSocket>
#include <QDataStream>
#include <QtDebug>
#include <QThread>
#include <QEvent>
#include <time.h>
#include <QMutex>

#define DEBUG_ON    0
#define DEBUG if(DEBUG_ON)




HPSCEventHandler::HPSCEventHandler(QString host,quint32 port)
 : QObject(),
 m_host(host),
 m_port(port),
 m_dataStream(NULL),
 m_socket(NULL) 
{
	m_socketMutex = new QMutex();
	if(m_socketMutex)
		m_socket = new QTcpSocket();
	if(m_socket)
	{
		m_dataStream = new QDataStream(m_socket);
		connect(m_socket,SIGNAL(readyRead()),this,SLOT(readSocket()));
        m_socketTimer = new QTimer();
        connect(m_socketTimer,SIGNAL(timeout()),this,SLOT(connectionLost()));
        m_socketTimer->start(1000);
        
	}
    
}


HPSCEventHandler::~HPSCEventHandler()
{
}



/*!
    \fn HPSCEventHandler::dataStream()
 */
QDataStream * HPSCEventHandler::dataStream()
{
    return m_dataStream;
}


/*!
    \fn HPSCEventHandler::socket()
 */
QTcpSocket * HPSCEventHandler::socket()
{
    return m_socket;
}


/*!
    \fn HPSCEventHandler::readSocket()
 */
void HPSCEventHandler::readSocket()
{
    
	MSGTYPE msgType;
	quint8 err=0;
	float volt=-1.0,amper=-1.0;
	int src;
	m_socketTimer->stop();
	if(m_socketMutex->tryLock())
	{
		while(m_socket->bytesAvailable()>=sizeof(msgType))
		{
			*m_dataStream>>msgType;
            DEBUG qDebug()<<"msgType:"<<(int)msgType;
			switch(msgType)
			{
				case MSG_ERR:*m_dataStream>>src;
				*m_dataStream>>err;              
				switch(src)
				{
					case 1: if(err == V_ERR) DEBUG qDebug()<<"SRC1 V ERROR";
					else DEBUG qDebug()<<"SRC1 A ERROR";
					break;
					case 2:if(err == V_ERR) DEBUG qDebug()<<"SRC2 V ERROR";
					else DEBUG qDebug()<<"SRC2 A ERROR";
					break;
					case 3:if(err == V_ERR) DEBUG qDebug()<<"SRC3 V ERROR";
					else DEBUG qDebug()<<"SRC3 A ERROR";
					break;
					case 4:if(err == V_ERR) DEBUG qDebug()<<"SRC4 V ERROR";
					else DEBUG qDebug()<<"SRC4 A ERROR";
					break;
				}
							
				break;
				case MSG_READOUT:
                    if(m_socket->bytesAvailable()>= sizeof(src)+sizeof(volt)+sizeof(amper))
                    {
                        *m_dataStream>>src;
                        *m_dataStream>>volt;
                        *m_dataStream>>amper;
                            //checkHPSClimits(src,volt,amper);
                    //TODO: check which buses are active and see if the 
                    //read values are what they are supposed to be
                        DEBUG qDebug()<<"*Readout: src:"<<src<<" volt:"<<volt<<" amper:"<<amper;
                        emit sig_hpscReadout(src,volt,amper);
                    }
                    break;
                case MSG_READOUT_V:
                    if(m_socket->bytesAvailable()>= sizeof(src)+sizeof(volt))
                    {
                        *m_dataStream>>src;
                        *m_dataStream>>volt;
                        DEBUG qDebug()<<"*Readout: src:"<<src<<" volt:"<<volt;
                        emit sig_hpscReadoutV(src,volt);
                    }   
				    break;
                case MSG_READOUT_A:
                    if(m_socket->bytesAvailable()>= sizeof(src)+sizeof(amper))
                    {
                        *m_dataStream>>src;
                        *m_dataStream>>amper;
                        DEBUG qDebug()<<"*Readout: src:"<<src<<" amper:"<<amper;
                        emit sig_hpscReadoutA(src,amper);
                    }   
                    break;
                default: DEBUG qDebug()<<"HPSCEventHandler::readSocket(): msgType unknown";
                    break;
					
			}    
		}
		m_socketMutex->unlock();
	}
	m_socketTimer->start(1000);
}


/*!
    \fn HPSCEventHandler::customEvent(QEvent *event)
 */
void HPSCEventHandler::customEvent(QEvent *event)
{
    DEBUG qDebug()<<"HPSCEventHandler::customEvent";
    m_socketTimer->stop();
    switch(event->type())
    {
        case HPSCEvent://DEBUG qDebug()<<(int)cmd.cmd<<" "<<cmd.var<<" "<<cmd.usWait<<"size:"<<sizeof(cmd);
                        if(m_socketMutex->tryLock())
                        {
                            *m_dataStream<<(quint32)event->type()<<((HPSCSocketEvent*)event)->command();
                            m_socket->flush();
                            m_socketMutex->unlock();
                        }
                        break;
         case HPSCEventSerial://DEBUG qDebug()<<(int)cmd.cmd<<" "<<cmd.var<<" "<<cmd.usWait<<"size:"<<sizeof(cmd);
                        if(m_socketMutex->tryLock())
                        {
                            *m_dataStream<<(quint32)event->type()<<((HPSCSocketEvent*)event)->serialConnect();
                            for(int i=0;i<sizeof(HPSC_Command)-sizeof(bool);++i)
                                *m_dataStream<<(quint8)255; //pad packet size to match HPSC_Command size
                            m_socket->flush();
                            m_socketMutex->unlock();
                        }
                        break;
        default:
            break;
      
      
    }
    m_socketTimer->start(1000);
}


/*!
    \fn HPSCEventHandler::socketMutex()
 */
QMutex * HPSCEventHandler::socketMutex()
{
	return m_socketMutex;
}


/*!
    \fn HPSCEventHandler::connectionLost()
 */
void HPSCEventHandler::connectionLost()
{
    DEBUG qDebug()<<"HPSCEventHandler::connectionLost";
    emit sig_hpscDisconnected();
    //m_socket->connectToHost(m_host,m_port);
    m_socketTimer->start(1000);
}



/*!
    \fn HPSCEventHandler::sendHPSCCommand(HPSC_Command command, int type)
 */
void HPSCEventHandler::sendHPSCCommand(HPSC_Command command, int type)
{
    *m_dataStream<<type<<command;
}
